package com.carter.springframework.core;

import cn.hutool.core.lang.Assert;
import com.carter.springframework.beans.exception.BeanException;
import com.sun.istack.internal.Nullable;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;

public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {

    private final Map<String,Object> attributes = new LinkedHashMap<String,Object>();

    @Override
    public void setAttribute(String name, Object value) {
        if (name==null){
            throw new BeanException("attribute名称不能为空");
        }
        if (value!=null){
            attributes.put(name,value);
        } else{
            removeAttribute(name);
        }
    }

    @Override
    public Object getAttribute(String name) {
        Assert.notNull(name,"name must not be null");
        return attributes.get(name);
    }

    @Override
    @Nullable
    public Object removeAttribute(String name) {
        Assert.notNull(name, "Name must not be null");
        return this.attributes.remove(name);
    }

    @Override
    public boolean hasAttribute(String name) {
        Assert.notNull(name, "Name must not be null");
        return this.attributes.containsKey(name);
    }

    @Override
    public String[] attributeNames() {
        return attributes.keySet().toArray(new String[0]);
    }

    protected void copyAttributesFrom(AttributeAccessor source){
        Assert.notNull(source,"source must not be null");
        String[] attributeNames = source.attributeNames();
        for (String attributeName : attributeNames) {
            setAttribute(attributeName,source.getAttribute(attributeName));
        }
    }

    @Override
    public boolean equals(@Nullable Object other) {
        return (this == other || (other instanceof AttributeAccessorSupport &&
                this.attributes.equals(((AttributeAccessorSupport) other).attributes)));
    }

    @Override
    public int hashCode() {
        return this.attributes.hashCode();
    }
}
